# ========================================================
# Replication Script for:
# "Dilutive Drift: The Racial Impact of Low-Change Maps"
# Perspectives on Politics (forthcoming)
# Author: Ursula Hackett
# Date: October 2025
# ========================================================

library(tidyverse)
library(sf)
library(corrr)
library(units)
library(geosphere)
library(marginaleffects)
library(patchwork)
library(lme4)
library(modelsummary)
library(kableExtra)
library(gt)
library(viridis)
library(knitr)
library(ggpattern)
library(ggrepel)

load("NEW_combined_measures.rdata") # Main dataset (embargoed until publication of research monograph)
load("RMD_raw_polygons.rdata") # Raw shapefiles
load("prepostgeojson.rdata") # Raw shapefiles
load("wiscmissmaps.rdata") # Raw shapefiles
load("bars_for_pop.rdata") # Quartile data
load("state_race.rdata") # Race data
load("avg_race_pc.rdata") # Race data
load("race_for_perspectives.rdata") # Race data
load("race_joined_post2005.rdata") # Race data
load("combined_gini_table.rdata") # Gini table


# ============================================
# Figure 1: Alabama district maps
# ============================================

AL_112_df <- polygons112 %>%
  filter(STATEFP == "01")

AL_117_df <- polygons117 %>%
  filter(STATEFP == "01")

AL_118_df <- polygons118 %>%
  filter(STATEFP20 == "01")

AL_map_112 <- ggplot() +
  geom_sf(data = AL_112_df, alpha = 0) +
  theme_void()

AL_map_117 <- ggplot() +
  geom_sf(data = AL_117_df, alpha = 0) +
  theme_void()

AL_map_118 <- ggplot() +
  geom_sf(data = AL_118_df, alpha = 0) +
  theme_void()

AL_maps <- (AL_map_112 | AL_map_117 | AL_map_118)
AL_maps

# ========================================================
# Figure 2: Average MAPS Scores by Cycle
# ========================================================

combined_dataframe_post1900 <- combined_dataframe %>% 
  filter(first_cong >=57)

post1900_cycles <- combined_dataframe_post1900 %>% 
  filter(first_cong %in% c("57", "62", "67", "72", "77", "82", "87", "92", "97", "102", "107", "112", "117"))


MAPS_stats <- post1900_cycles %>% 
  group_by(decade) %>% 
  summarise(mean_MAPS = mean(change_index),
            sd_MAPS = sd(change_index),
            max_MAPS = max(change_index),
            min_MAPS = min(change_index)) %>% 
  ungroup()

ggplot(MAPS_stats, aes(x = factor(decade),
                       y = mean_MAPS)) +
  geom_bar(stat = "identity", position = "dodge", fill = "grey20") +
  labs(x = "Cycle",
       y = "Average MAPS Scores") +
  theme_minimal()

# ========================================================
# Table 2: States with Lowest Mean Change, by Cycle
# ========================================================

combined_dataframe_post1960 <- combined_dataframe %>% 
  filter(first_cong >=87)

combined_dataframe_post1960_redcyc <- combined_dataframe_post1960 %>%
  filter(first_cong == 87 | 
           first_cong == 92 | 
           first_cong == 97 | 
           first_cong == 102 | 
           first_cong == 107 | 
           first_cong == 112 | 
           first_cong == 117)

combined_post1960_redcyc_4plus <- combined_dataframe_post1960_redcyc %>%
  group_by(STATEFP, which_cong) %>%
  filter(n_distinct(GEOID_pre) > 3) %>%
  ungroup()

mean_change <- combined_post1960_redcyc_4plus %>%
  group_by(STATEFP, which_cong) %>%
  summarize(mean_change = mean(change_index, na.rm = TRUE))

mean_change <- mean_change %>%
  mutate(STATEFP = as.factor(STATEFP))

fips <- read.csv("fips.csv", as.is = T)

fips <- fips %>%
  mutate(stusps = ifelse(stusps %in% c("1", "2", "3", "4", "5", "6", "7", "8", "9"),
                         paste0("0", stusps),
                         stusps))

fips <- fips %>%
  mutate(stusps = as.factor(stusps))

mean_change <- mean_change %>% 
  left_join(fips, by = c("STATEFP" = "stusps"))

lowest_mean_change <- mean_change %>%
  group_by(which_cong) %>%
  top_n(-10, wt = mean_change) %>%
  arrange(which_cong, mean_change)

cycle_years <- c("87_88", "92_93", "97_98", "102_103", "107_108", "112_113", "117_118")

summary_table <- lowest_mean_change %>%
  group_by(which_cong) %>%
  top_n(-10, wt = mean_change) %>%
  arrange(match(which_cong, cycle_years), mean_change) %>%
  mutate(state_with_score = paste0(st, " (", sprintf("%.2f", mean_change), ")")) %>%
  summarize(states = paste(state_with_score, collapse = ", ")) %>%
  rename(`Cycle` = which_cong, `Least-change states` = states)

summary_table$`Cycle` <- case_when(
  summary_table$`Cycle` == "87_88" ~ "1960",
  summary_table$`Cycle` == "92_93" ~ "1970",
  summary_table$`Cycle` == "97_98" ~ "1980",
  summary_table$`Cycle` == "102_103" ~ "1990",
  summary_table$`Cycle` == "107_108" ~ "2000",
  summary_table$`Cycle` == "112_113" ~ "2010",
  summary_table$`Cycle` == "117_118" ~ "2020",
  TRUE ~ as.character(summary_table$`Cycle`)
)

summary_table <- summary_table %>%
  arrange(desc(`Cycle`))

knitr::kable(summary_table, caption = "States with the Lowest Mean Change in each Redistricting Cycle, 1960-2020", 
             linesep = "\\addlinespace") %>% 
  kable_styling(latex_options = "HOLD_position") %>% 
  kable_styling(latex_options="scale_down")

# ========================================================
# Figure 3: Black Representatives Change by MAPS Scores
# ========================================================

ggplot(quartile_change, aes(x = factor(MAPS_quartile),
                            y = n,
                            fill = black_bucket)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(x = element_blank(),
       y = "Number of State-Cycle Combinations",
       fill = "Black Representatives") +
  scale_fill_manual(values = c("Gains" = "black",
                               "No change" = "grey80",
                               "Loses" = "grey40")) +
  scale_y_continuous(limits = c(0,100)) +
  theme_minimal()

# ========================================================
# Figure 4: Female Representatives Change by MAPS Scores
# ========================================================

ggplot(women_quartile_change, aes(x = factor(MAPS_quartile),
                                  y = n,
                                  fill = women_bucket)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(x = element_blank(),
       y = "Number of State-Cycle Combinations",
       fill = "Female Representatives") +
  scale_fill_manual(values = c("Gains" = "black",
                               "No change" = "grey80",
                               "Loses" = "grey40")) +
  scale_y_continuous(limits = c(0,100)) +
  theme_minimal()

# ========================================================
# Figure 5: Wisconsin District Maps
# ========================================================

WI_map_3_112 <- ggplot() +
  geom_sf(data = WI_112_3_df, alpha = 0) +
  theme_void() 

WI_map_3_113 <- ggplot() +
  geom_sf(data = WI_113_3_df, alpha = 0) +
  theme_void() 

WI_map_3_118 <- ggplot() +
  geom_sf(data = WI_118_3_df, alpha = 0) +
  theme_void() 

wi_party <- (WI_map_3_112 | WI_map_3_113 | WI_map_3_118)
wi_party


# ========================================================
# Figure 6: Stylized Dot Plot
# ========================================================

dots <- data.frame(
  x = rep(1:4, 4),
  y = rep(4:1, each = 4),
  color = rep("white", 16)
)

dots <- dots %>% 
  mutate(color = case_when(x == 1 & y == 4 ~ "black",
                           x == 1 & y == 3 ~ "black",
                           x == 2 & y == 4 ~ "black",
                           x == 1 & y == 2 ~ "black",
                           x == 4 & y == 2 ~ "black",
                           x == 4 & y == 3 ~ "black",
                           .default = "white"))

# Define the label coordinates and text
orig_label_x_dis1 <- 1.5  # X-coordinate for the label
orig_label_y_dis1 <- 3.5  # Y-coordinate for the label
orig_label_text_dis1 <- "1"  # Text for the label

# Define the label coordinates and text
orig_label_x_dis2 <- 1.5  # X-coordinate for the label
orig_label_y_dis2 <- 1.5  # Y-coordinate for the label
orig_label_text_dis2 <- "2"  # Text for the label

# Define the label coordinates and text
orig_label_x_dis3 <- 3.5  # X-coordinate for the label
orig_label_y_dis3 <- 3.5  # Y-coordinate for the label
orig_label_text_dis3 <- "3"  # Text for the label

# Define the label coordinates and text
orig_label_x_dis4 <- 3.5  # X-coordinate for the label
orig_label_y_dis4 <- 1.5  # Y-coordinate for the label
orig_label_text_dis4 <- "4"  # Text for the label

# Plot the dots
orig_dots_plot <- ggplot(dots, aes(x, y, fill = color)) +
  geom_point(shape = 21, size = 10, color = "black") +
  geom_rect(aes(xmin = 0.5, xmax = 2.5, ymin = 2.5, ymax = 4.5), color = "blue", fill = NA) +
  geom_rect(aes(xmin = 2.5, xmax = 4.5, ymin = 2.5, ymax = 4.5), color = "blue", fill = NA) +
  geom_rect(aes(xmin = 0.5, xmax = 2.5, ymin = 0.5, ymax = 2.5), color = "blue", fill = NA) +
  geom_rect(aes(xmin = 2.5, xmax = 4.5, ymin = 0.5, ymax = 2.5), color = "blue", fill = NA) +
  geom_text(aes(x = orig_label_x_dis1, y = orig_label_y_dis1, label = orig_label_text_dis1), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = orig_label_x_dis2, y = orig_label_y_dis2, label = orig_label_text_dis2), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = orig_label_x_dis3, y = orig_label_y_dis3, label = orig_label_text_dis3), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = orig_label_x_dis4, y = orig_label_y_dis4, label = orig_label_text_dis4), size = 5, color = "black", fontface = "bold") +
  scale_fill_identity() +
  theme_void() +
  coord_fixed(ratio = 1) +
  theme(legend.position = "none")

orig_dots_plot

# ========================================================
# Figure 7: Passive Packing (Dot Plot)
# ========================================================

exp_dots <- data.frame(
  x = rep(1:5, each = 4),
  y = rep(4:1, times = 5),
  color = rep("white", 20)
)

exp_dots <- exp_dots %>% 
  mutate(color = case_when(x == 1 & y == 4 ~ "black",
                           x == 1 & y == 3 ~ "black",
                           x == 2 & y == 4 ~ "black",
                           x == 2 & y == 3 ~ "black",
                           x == 1 & y == 2 ~ "black",
                           x == 2 & y == 2 ~ "black",
                           x == 3 & y == 3 ~ "black",
                           x == 4 & y == 3 ~ "black",
                           x == 4 & y == 2 ~ "black",
                           x == 5 & y == 2 ~ "black",
                           .default = "white"))

# Create a data frame with coordinates for the custom polygon enclosing the specified dots
polygon_df <- data.frame(
  x = c(0.5, 0.5, 2.5, 2.5, 3.5, 3.5, 0.5),
  y = c(2.5, 4.5, 4.5, 3.5, 3.5, 2.5, 2.5)
)

polygon_df2 <- data.frame(
  x = c(0.5, 0.5, 2.5, 2.5, 3.5, 3.5, 0.5),
  y = c(0.5, 2.5, 2.5, 1.5, 1.5, 0.5, 0.5)
)

polygon_df3 <- data.frame(
  x = c(2.5, 2.5, 5.5, 5.5, 3.5, 3.5, 2.5),
  y = c(3.5, 4.5, 4.5, 2.5, 2.5, 3.5, 3.5)
)

polygon_df4 <- data.frame(
  x = c(3.5, 3.5, 2.5, 2.5, 5.5, 5.5, 3.5),
  y = c(0.5, 1.5, 1.5, 2.5, 2.5, 0.5, 0.5)
)

# Define the label coordinates and text
label_x_dis1 <- 1.5  # X-coordinate for the label
label_y_dis1 <- 3.5  # Y-coordinate for the label
label_text_dis1 <- "1"  # Text for the label

# Define the label coordinates and text
label_x_dis2 <- 1.5  # X-coordinate for the label
label_y_dis2 <- 1.5  # Y-coordinate for the label
label_text_dis2 <- "2"  # Text for the label

# Define the label coordinates and text
label_x_dis3 <- 4.5  # X-coordinate for the label
label_y_dis3 <- 3.5  # Y-coordinate for the label
label_text_dis3 <- "3"  # Text for the label

# Define the label coordinates and text
label_x_dis4 <- 4.5  # X-coordinate for the label
label_y_dis4 <- 1.5  # Y-coordinate for the label
label_text_dis4 <- "4"  # Text for the label

# Plot the dots and polygon
exp_dots_plot <- ggplot(exp_dots, aes(x, y, fill = color)) +
  geom_point(shape = 21, size = 10, color = "black") +
  geom_polygon(data = polygon_df, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df2, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df3, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df4, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_text(aes(x = label_x_dis1, y = label_y_dis1, label = label_text_dis1), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis2, y = label_y_dis2, label = label_text_dis2), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis3, y = label_y_dis3, label = label_text_dis3), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis4, y = label_y_dis4, label = label_text_dis4), size = 5, color = "black", fontface = "bold") +
  scale_fill_identity() +
  theme_void() +
  coord_fixed(ratio = 1) +
  theme(legend.position = "none")


#Now make the extra representation (non packing, concentrated pop growth)
# Create a data frame with coordinates for the custom polygon enclosing the specified dots
polygon_df5 <- data.frame(
  x = c(0.5, 0.5, 3.5, 3.5, 2.5, 2.5, 0.5),
  y = c(2.5, 4.5, 4.5, 3.5, 3.5, 2.5, 2.5)
)

polygon_df6 <- data.frame(
  x = c(0.5, 0.5, 2.5, 2.5, 3.5, 3.5, 1.5, 1.5, 0.5),
  y = c(0.5, 2.5, 2.5, 3.5, 3.5, 1.5, 1.5, 0.5, 0.5)
)

polygon_df7 <- data.frame(
  x = c(3.5, 3.5, 5.5, 5.5, 4.5, 4.5, 3.5),
  y = c(2.5, 4.5, 4.5, 1.5, 1.5, 2.5, 2.5)
)

polygon_df8 <- data.frame(
  x = c(1.5, 1.5, 3.5, 3.5, 4.5, 4.5, 5.5, 5.5, 1.5),
  y = c(0.5, 1.5, 1.5, 2.5, 2.5, 1.5, 1.5, 0.5, 0.5)
)

# Define the label coordinates and text
label_x_dis5 <- 1.5  # X-coordinate for the label
label_y_dis5 <- 3.5  # Y-coordinate for the label
label_text_dis5 <- "1"  # Text for the label

# Define the label coordinates and text
label_x_dis6 <- 2.5  # X-coordinate for the label
label_y_dis6 <- 2  # Y-coordinate for the label
label_text_dis6 <- "2"  # Text for the label

# Define the label coordinates and text
label_x_dis7 <- 4.5  # X-coordinate for the label
label_y_dis7 <- 3.5  # Y-coordinate for the label
label_text_dis7 <- "3"  # Text for the label

# Define the label coordinates and text
label_x_dis8 <- 4.5  # X-coordinate for the label
label_y_dis8 <- 1  # Y-coordinate for the label
label_text_dis8 <- "4"  # Text for the label

# Plot the dots and polygon
exp_dots_plot_nopack <- ggplot(exp_dots, aes(x, y, fill = color)) +
  geom_point(shape = 21, size = 10, color = "black") +
  geom_polygon(data = polygon_df5, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df6, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df7, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df8, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_text(aes(x = label_x_dis5, y = label_y_dis5, label = label_text_dis5), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis6, y = label_y_dis6, label = label_text_dis6), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis7, y = label_y_dis7, label = label_text_dis7), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis8, y = label_y_dis8, label = label_text_dis8), size = 5, color = "black", fontface = "bold") +
  scale_fill_identity() +
  theme_void() +
  coord_fixed(ratio = 1) +
  theme(legend.position = "none")

exp_dots_plot + ggtitle("Panel A: Passive Packing") + exp_dots_plot_nopack + ggtitle("Panel B: Active Response")

# ========================================================
# Figure 8: Passive Cracking (Dot Plot)
# ========================================================

disp_exp_dots <- data.frame(
  x = rep(1:5, each = 4),
  y = rep(4:1, times = 5),
  color = rep("white", 20)
)

disp_exp_dots <- disp_exp_dots %>% 
  mutate(color = case_when(x == 1 & y == 4 ~ "black",
                           x == 1 & y == 3 ~ "black",
                           x == 2 & y == 4 ~ "black",
                           x == 2 & y == 2 ~ "black",
                           x == 1 & y == 1 ~ "black",
                           x == 4 & y == 4 ~ "black",
                           x == 5 & y == 3 ~ "black",
                           x == 4 & y == 1 ~ "black",
                           x == 5 & y == 2 ~ "black",
                           x == 3 & y == 3 ~ "black",
                           .default = "white"))

# Create a data frame with coordinates for the custom polygon enclosing the specified dots
polygon_df9 <- data.frame(
  x = c(0.5, 0.5, 2.5, 2.5, 3.5, 3.5, 0.5),
  y = c(2.5, 4.5, 4.5, 3.5, 3.5, 2.5, 2.5)
)

polygon_df10 <- data.frame(
  x = c(0.5, 0.5, 2.5, 2.5, 3.5, 3.5, 0.5),
  y = c(0.5, 2.5, 2.5, 1.5, 1.5, 0.5, 0.5)
)

polygon_df11 <- data.frame(
  x = c(2.5, 2.5, 5.5, 5.5, 3.5, 3.5, 2.5),
  y = c(3.5, 4.5, 4.5, 2.5, 2.5, 3.5, 3.5)
)

polygon_df12 <- data.frame(
  x = c(3.5, 3.5, 2.5, 2.5, 5.5, 5.5, 3.5),
  y = c(0.5, 1.5, 1.5, 2.5, 2.5, 0.5, 0.5)
)

# Define the label coordinates and text
label_x_dis9 <- 1.5  # X-coordinate for the label
label_y_dis9 <- 3.5  # Y-coordinate for the label
label_text_dis9 <- "1"  # Text for the label

# Define the label coordinates and text
label_x_dis10 <- 1.5  # X-coordinate for the label
label_y_dis10 <- 1.5  # Y-coordinate for the label
label_text_dis10 <- "2"  # Text for the label

# Define the label coordinates and text
label_x_dis11 <- 4.5  # X-coordinate for the label
label_y_dis11 <- 3.5  # Y-coordinate for the label
label_text_dis11 <- "3"  # Text for the label

# Define the label coordinates and text
label_x_dis12 <- 4.5  # X-coordinate for the label
label_y_dis12 <- 1.5  # Y-coordinate for the label
label_text_dis12 <- "4"  # Text for the label

# Plot the dots and polygon
disp_exp_dots_plot_crack <- ggplot(disp_exp_dots, aes(x, y, fill = color)) +
  geom_point(shape = 21, size = 10, color = "black") +
  geom_polygon(data = polygon_df9, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df10, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df11, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df12, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_text(aes(x = label_x_dis9, y = label_y_dis9, label = label_text_dis9), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis10, y = label_y_dis10, label = label_text_dis10), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis11, y = label_y_dis11, label = label_text_dis11), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis12, y = label_y_dis12, label = label_text_dis12), size = 5, color = "black", fontface = "bold") +
  scale_fill_identity() +
  theme_void() +
  coord_fixed(ratio = 1) +
  theme(legend.position = "none")

polygon_df13 <- data.frame(
  x = c(0.5, 0.5, 2.5, 2.5, 1.5, 1.5, 0.5),
  y = c(1.5, 4.5, 4.5, 2.5, 2.5, 1.5, 1.5)
)

polygon_df14 <- data.frame(
  x = c(0.5, 0.5, 1.5, 1.5, 2.5, 2.5, 4.5, 4.5, 0.5),
  y = c(0.5, 1.5, 1.5, 2.5, 2.5, 1.5, 1.5, 0.5, 0.5)
)

polygon_df15 <- data.frame(
  x = c(2.5, 2.5, 5.5, 5.5, 3.5, 3.5, 2.5),
  y = c(3.5, 4.5, 4.5, 2.5, 2.5, 3.5, 3.5)
)

polygon_df16 <- data.frame(
  x = c(2.5, 2.5, 3.5, 3.5, 5.5, 5.5, 4.5, 4.5, 2.5),
  y = c(1.5, 3.5, 3.5, 2.5, 2.5, 0.5, 0.5, 1.5, 1.5)
)

# Define the label coordinates and text
label_x_dis13 <- 1.5  # X-coordinate for the label
label_y_dis13 <- 3.5  # Y-coordinate for the label
label_text_dis13 <- "1"  # Text for the label

# Define the label coordinates and text
label_x_dis14 <- 2.5  # X-coordinate for the label
label_y_dis14 <- 1  # Y-coordinate for the label
label_text_dis14 <- "2"  # Text for the label

# Define the label coordinates and text
label_x_dis15 <- 4.5  # X-coordinate for the label
label_y_dis15 <- 3.5  # Y-coordinate for the label
label_text_dis15 <- "3"  # Text for the label

# Define the label coordinates and text
label_x_dis16 <- 3.5  # X-coordinate for the label
label_y_dis16 <- 2  # Y-coordinate for the label
label_text_dis16 <- "4"  # Text for the label

# Plot the dots and polygon
disp_exp_dots_plot_nocrack <- ggplot(disp_exp_dots, aes(x, y, fill = color)) +
  geom_point(shape = 21, size = 10, color = "black") +
  geom_polygon(data = polygon_df13, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df14, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df15, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_polygon(data = polygon_df16, aes(x, y), color = "blue", fill = NA, size = 1) +
  geom_text(aes(x = label_x_dis13, y = label_y_dis13, label = label_text_dis13), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis14, y = label_y_dis14, label = label_text_dis14), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis15, y = label_y_dis15, label = label_text_dis15), size = 5, color = "black", fontface = "bold") +
  geom_text(aes(x = label_x_dis16, y = label_y_dis16, label = label_text_dis16), size = 5, color = "black", fontface = "bold") +
  scale_fill_identity() +
  theme_void() +
  coord_fixed(ratio = 1) +
  theme(legend.position = "none")

disp_exp_dots_plot_crack + ggtitle("Panel A: Passive Cracking") + disp_exp_dots_plot_nocrack + ggtitle("Panel B: Active Response")

# ========================================================
# Figure 9: Dilutive Drift is Remedied in Alabama
# ========================================================

# Define label text and coordinates
pre_label_data <- data.frame(
  label = c("1", "2", "3", "4", "5", "6", "7"),
  lon = c(-88, -86, -85.8, -87.5, -86.5, -86.9, -87.75),
  lat = c(30.75, 31.5, 33.2, 34, 34.8, 33, 32.5)
)

post_label_data <- data.frame(
  label = c("1", "2", "3", "4", "5", "6", "7"),
  lon = c(-86.5, -86, -85.8, -87.5, -86.5, -86.5, -87.75),
  lat = c(31.2, 31.9, 33.5, 34, 34.8, 32.8, 32.5)
)

# Create base plots with the spatial data
pre_base_plot <- ggplot() +
  geom_sf(data = pre_geojson_data) +
  theme_void()

post_base_plot <- ggplot() +
  geom_sf(data = post_geojson_data) +
  theme_void()

# Filter the data for Districts = 7
pre_district_7 <- pre_geojson_data %>%
  filter(Districts == 7)
post_district_7 <- post_geojson_data %>%
  filter(Districts == 7)

# Filter the data for Districts = 2
post_district_2 <- post_geojson_data %>%
  filter(Districts == 2)

# Add plain grey fill to Districts = 7
pre_plot_with_fill <- pre_base_plot +
  geom_sf(data = pre_district_7, fill = "grey30") +
  geom_sf(data = pre_geojson_data %>% filter(Districts != 7), fill = "white") +  # Fill other districts with white
  theme_void()

# Add plain grey fill to Districts = 7 and 2
post_plot_with_fill <- post_base_plot +
  geom_sf(data = post_district_7, fill = "grey30") +
  geom_sf(data = post_district_2, fill = "grey60") +
  geom_sf(data = post_geojson_data %>% filter(!(Districts %in% c(2, 7))), fill = "white") +  # Fill other districts with white
  theme_void()

# Plot the maps with hatching in Districts = 7 (pre-change map) and different hatching in Districts = 2 and 7 (post-change map)
pre_plot_with_fill + geom_text(data = pre_label_data, aes(x = lon, y = lat, label = label)) + ggtitle("Old map (11.4.21-10.5.23)") |
  post_plot_with_fill + geom_text(data = post_label_data, aes(x = lon, y = lat, label = label)) + ggtitle("New map (10.5.23 -)")

# ========================================================
# Figure 10: Dilutive Drift is remedied in Louisiana
# ========================================================

la_pre_label_data <- data.frame(
  label = c("1", "2", "3", "4", "5", "6"),
  lon = c(-89.7, -90.7, -92.5, -93.5, -92, -90.8),
  lat = c(29.5, 30, 30, 32, 32, 30.4)
)

la_post_label_data <- data.frame(
  label = c("1", "2", "3", "4", "5", "6"),
  lon = c(-89.7, -91, -92.1, -93, -90.7, -91.8),
  lat = c(29.5, 30, 29.8, 32.6, 30.8, 30.8)
)


# Create base plots with the spatial data
la_pre_base_plot <- ggplot() +
  geom_sf(data = la_pre_geojson_data) +
  theme_void()

la_post_base_plot <- ggplot() +
  geom_sf(data = la_post_geojson_data) +
  theme_void()

# Filter the data for Districts = 7
la_pre_district_6 <- la_pre_geojson_data %>%
  filter(Districts == 6)
la_post_district_6 <- la_post_geojson_data %>%
  filter(Districts == 6)

# Filter the data for Districts = 6
la_post_district_2 <- la_post_geojson_data %>%
  filter(Districts == 2)

# Add hatching to Districts = 7
la_pre_plot_with_fill <- la_pre_base_plot +
  geom_sf(data = la_pre_district_6, fill = "grey30") +
  geom_sf(data = la_pre_geojson_data %>% filter(Districts !=6), fill = "white") +  # Fill other districts with white
  theme_void()

# Add hatching to Districts = 7
la_post_plot_with_fill <- la_post_base_plot +
  geom_sf(data = la_post_district_6, fill = "grey30") +
  geom_sf(data = la_post_district_2, fill = "grey60") +
  geom_sf(data = la_post_geojson_data %>% filter(!(Districts %in% c(2, 6))), fill = "white") +  # Fill other districts with white
  theme_void()

# Plot the maps with hatching in Districts = 7 (pre-change map) and different hatching in Districts = 6 and 7 (post-change map)
la_pre_plot_with_fill + geom_text(data = la_pre_label_data, aes(x = lon, y = lat, label = label)) + ggtitle("Old map (3.31.22-1.22.24)") | la_post_plot_with_fill + geom_text(data = la_post_label_data, aes(x = lon, y = lat, label = label)) + ggtitle("New map (1.22.24 - pending review)")

# ========================================================
# End of Main Script
# ========================================================

################################### APPENDIX ############################################################

# ========================================================
# Appendix Figure 1: Blacks Gini Coefficient Scatter
# ========================================================

blacks_scatter_plot <- ggplot(data = avg_race_pc, aes(x = blacks_gini_coefficient, y = black_pc_state)) +
  geom_point() +  # Adds the scatter plot points
  geom_text(data = subset(avg_race_pc, st %in% c("Alabama", "Louisiana", "South Carolina", "Arkansas", "Wisconsin")),
            aes(label = st), vjust = -1, hjust = 1) +
  labs(
    x = "Blacks Gini Coefficient",
    y = "Blacks as Percentage of State Population"
  ) +
  theme_minimal()  # Applies a minimalistic theme

blacks_scatter_plot + 
  annotate("text", x = 0.04, y = 2, label = "Idaho") +
  annotate("text", x = 0.15, y = 37, label = "Mississippi") 

# ========================================================
# Appendix Figure 2: Latino Gini Coefficient Scatter
# ========================================================

hisp_scatter_plot <- ggplot(data = avg_race_pc, aes(x = hispanics_gini_coefficient, y = hisp_pc_state)) +
  geom_point() +  # This adds the scatter plot points
  geom_text(data = subset(avg_race_pc, st %in% c("California", "Pennsylvania", "Nevada", "Florida")),
            aes(label = st), vjust = -1, hjust = 1) +
  labs(
    x = "Latinos Gini Coefficient",
    y = "Latinos as Percentage of State Population"
  ) +
  theme_minimal()  # Applies a minimalistic theme

hisp_scatter_plot + 
  annotate("text", x = 0.29, y = 40, label = "Texas") +
  annotate("text", x = 0.05, y = 48, label = "New Mexico")

# ========================================================
# Appendix Figure 3: Changes in Gini Coefficient over time, selected states
# ========================================================

fips <- read.csv("fips.csv", as.is = T)

fips <- fips %>% 
  mutate(stusps = as.character(stusps))

fips <- fips %>%
  mutate(stusps = ifelse(stusps %in% c("1", "2", "3", "4", "5", "6", "7", "8", "9"),
                         paste0("0", stusps),
                         stusps))

calculate_gini <- function(blacks) {
  gini <- ineq::Gini(blacks)
  return(gini)
}

combined_race_df <- combined_race_df %>%
  group_by(state, year)

blacks_data <- combined_race_df %>%
  select(state, year, GEOID, blacks)

black_gini_coefficients <- blacks_data %>%
  summarize(blacks_gini_coefficient = calculate_gini(blacks))

whites_data <- combined_race_df %>%
  select(state, year, GEOID, whites)

white_gini_coefficients <- whites_data %>%
  summarize(whites_gini_coefficient = calculate_gini(whites))

hispanics_data <- combined_race_df %>%
  select(state, year, GEOID, hispanics)

hispanic_gini_coefficients <- hispanics_data %>%
  summarize(hispanics_gini_coefficient = calculate_gini(hispanics))

black_gini_coefficients <- black_gini_coefficients %>% 
  left_join(fips, by = c("state" = "stusps"))

states_of_interest <- c("01", "22", "28", "45", "05", "37")
filtered_data <- black_gini_coefficients %>% filter(state %in% states_of_interest)

line_types <- c("solid", "dashed", "dotted", "dotdash", "longdash", "twodash")

maxgini <- filtered_data %>% 
  filter(year==max(year))

p <- ggplot(filtered_data, aes(x = year, y = blacks_gini_coefficient, linetype = st)) +
  geom_line() +
  labs(x = "Year", y = "Black Gini Coefficient") +
  theme_minimal() +
  theme(legend.position = "none")

p + 
  geom_segment(aes(x = 2013.5, y = 0.27, xend = 2015.8, yend = 0.25), arrow = arrow(type = "open", length = unit(0.3, "cm")), color = "black") +
  geom_segment(aes(x = 2013.5, y = 0.14, xend = 2011, yend = 0.155), arrow = arrow(type = "open", length = unit(0.3, "cm")), color = "black") + 
  annotate("text", x = 2010, y = 0.277, label = "NC racial gerrymander ruling") +
  annotate("text", x = 2015, y = 0.133, label = "High change 2010 cycle packs LA District 2") +
  guides(color = guide_legend(override.aes = list(linetype = "solid"))) +
  geom_text(data=maxgini, aes(label=st), hjust="left")  +
  coord_cartesian(xlim = c(2005,2024.4),clip="off")

# ========================================================
# Appendix Figure 4: Plotting Model Results - Black, White, and Latino Gini Change by MAPS Scores
# ========================================================

black_2005_gini_model <- lmer(blacks_gc_change ~ change_index*first_cong + (1 | STATEFP), data = race_joined_post2005)

white_2005_gini_model <- lmer(whites_gc_change ~ change_index*first_cong + (1 | STATEFP), data = race_joined_post2005)

hisp_2005_gini_model <- lmer(hisp_gc_change ~ change_index*first_cong + (1 | STATEFP), data = race_joined_post2005)

black_2005_gini_avg_predictions <- avg_predictions(black_2005_gini_model, variables = "change_index")

white_2005_gini_avg_predictions <- avg_predictions(white_2005_gini_model, variables = "change_index")

hisp_2005_gini_avg_predictions <- avg_predictions(hisp_2005_gini_model, variables = "change_index")

combined_predictions <- bind_rows(
  mutate(black_2005_gini_avg_predictions, group = "Blacks"),
  mutate(white_2005_gini_avg_predictions, group = "Whites"),
  mutate(hisp_2005_gini_avg_predictions, group = "Latinos")
)

maxcombined_predictions <- combined_predictions %>% 
  filter(change_index==max(change_index))

p <- ggplot(combined_predictions, aes(x = change_index, y = estimate, group = group, linetype = group)) +
  geom_line(aes(color = group)) + 
  geom_ribbon(aes(ymin = conf.low, ymax = conf.high, fill = group), alpha = 0.2, color = NA) +
  xlab("Magnitude of District MAPS Change") +
  ylab("Changes in Unevenness of Population Distribution") +
  theme_minimal() +
  theme(
    panel.background = element_rect(fill = "white", color = NA),
    strip.background = element_blank(),  # Remove strip background
    strip.text = element_blank(),         # Remove strip text
    legend.position = "none"
  ) +
  scale_colour_manual(values = c("Blacks" = "#E1BE6A", "Whites" = "#40B0A6", "Latinos" = "#474795")) +
  scale_fill_manual(values = c("Blacks" = "#E1BE6A", "Whites" = "#40B0A6", "Latinos" = "#474795")) +
  scale_linetype_manual(values = c("Blacks" = "solid", "Whites" = "dotted", "Latinos" = "dashed"))

p + 
  geom_segment(aes(x = -0.4, y = 0.01, xend = -0.4, yend = 0.02), arrow = arrow(type = "open", length = unit(0.3, "cm")), color = "black") +
  geom_segment(aes(x = -0.4, y = -0.035, xend = -0.4, yend = -0.045), arrow = arrow(type = "open", length = unit(0.3, "cm")), color = "black") + 
  annotate("text", x = 1, y = 0.025, label = "Population more unevenly distributed") +
  annotate("text", x = 1, y = -0.05, label = "Population more evenly distributed") +
  guides(color = guide_legend(override.aes = list(linetype = "solid"))) +
  geom_text(data=maxcombined_predictions, aes(label=group), hjust="left") +
  coord_cartesian(xlim = c(-0.5,5.5),clip="off")

# ========================================================
# End of Appendix Script
# ========================================================